package cn.asiontang.launcher;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.text.Html;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;

import java.util.List;

import cn.asiontang.db.DBHelper;
import cn.asiontang.exception.LogEx;
import cn.asiontang.utils.ToastEx;
import eu.chainfire.libsuperuser.Shell;

class MainActivityListViewAdapter extends BaseAdapterEx3<AppInfo> implements View.OnClickListener//
        , AdapterView.OnItemClickListener//
        , AdapterView.OnItemLongClickListener
{
    private static String mLancherPackageName;
    /**
     * 显示系统APP的颜色
     */
    private final int mColorSystemAppAccent;
    private final int mColorSystemAppAccentCantLaunch;
    /**
     * 显示用户APP的颜色
     */
    private final int mColorUserAppAccent;
    private final int mColorUserAppAccentCantLaunch;
    private final PackageManager pm;
    private final ListView mListView;
    private boolean isQuickHideMode = false;
    private boolean isOnlyShowHideApp = false;

    @SuppressWarnings("deprecation")
    public MainActivityListViewAdapter(Context context, ListView listView)
    {
        super(context, R.layout.activity_main_listview_item);

        pm = mContext.getPackageManager();

        this.mListView = listView;
        this.mListView.setOnItemClickListener(this);
        this.mListView.setOnItemLongClickListener(this);

        //缓存常用的两种APP颜色
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
        {
            mColorSystemAppAccent = mContext.getResources().getColor(R.color.systemAppAccent, mContext.getTheme());
            mColorSystemAppAccentCantLaunch = mContext.getResources().getColor(R.color.systemAppAccentCantLaunch, mContext.getTheme());
            mColorUserAppAccent = mContext.getResources().getColor(R.color.userAppAccent, mContext.getTheme());
            mColorUserAppAccentCantLaunch = mContext.getResources().getColor(R.color.userAppAccentCantLaunch, mContext.getTheme());
        }
        else
        {
            mColorSystemAppAccent = mContext.getResources().getColor(R.color.systemAppAccent);
            mColorSystemAppAccentCantLaunch = mContext.getResources().getColor(R.color.systemAppAccentCantLaunch);
            mColorUserAppAccent = mContext.getResources().getColor(android.R.color.white);
            mColorUserAppAccentCantLaunch = mContext.getResources().getColor(R.color.userAppAccentCantLaunch);
        }
    }

    /**
     * 当前APP是否为桌面APP，或者系统签名的APP
     */
    public static boolean isAllowDisableApp(PackageManager pm, AppInfo appInfo)
    {
        try
        {
            if (mLancherPackageName == null)
            {
                //android-4.1.2_r2/packages/apps/Settings/src/com/android/settings/applications/InstalledAppDetails.java
                //http://osxr.org:8080/android/source/packages/apps/Settings/src/com/android/settings/applications/InstalledAppDetails.java

                // Try to prevent the user from bricking their phone
                // by not allowing disabling of apps signed with the
                // system cert and any launcher app in the system.
                Intent intent = new Intent(Intent.ACTION_MAIN);
                intent.addCategory(Intent.CATEGORY_HOME);
                List<ResolveInfo> homes = pm.queryIntentActivities(intent, 0);
                mLancherPackageName = homes.get(0).activityInfo.packageName;
            }
            if (appInfo.getPackageName().equals(mLancherPackageName))
                return false;

            @SuppressLint("PackageManagerGetSignatures")
            PackageInfo app = pm.getPackageInfo(appInfo.getPackageName(), PackageManager.GET_SIGNATURES);
            if (app != null && app.signatures != null)
            {
                @SuppressLint("PackageManagerGetSignatures")
                PackageInfo sys = pm.getPackageInfo("android", PackageManager.GET_SIGNATURES);
                if (sys.signatures[0].equals(app.signatures[0]))
                    return false;
            }
            return true;
        }
        catch (PackageManager.NameNotFoundException e)
        {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * <p>Intent to show an applications details page in (Settings) com.android.settings</p>
     *
     * @param context     The context associated to the application
     * @param packageName The package name of the application
     * @return the intent to open the application info screen.
     */
    public static Intent newAppDetailsIntent(Context context, String packageName)
    {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD)
        {
            Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
            intent.setData(Uri.parse("package:" + packageName));
            return intent;
        }
        else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.FROYO)
        {
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
            intent.setClassName("com.android.settings",
                    "com.android.settings.InstalledAppDetails");
            intent.putExtra("pkg", packageName);
            return intent;
        }
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
        intent.setClassName("com.android.settings",
                "com.android.settings.InstalledAppDetails");
        intent.putExtra("com.android.settings.ApplicationPkgName", packageName);
        return intent;
    }

    private boolean amForceStopApp(String packageName)
    {
        Shell.SU.run("am force-stop " + packageName);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1)
        {
            try
            {
                ApplicationInfo info = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
                return (info.flags & ApplicationInfo.FLAG_STOPPED) != 0;
            }
            catch (PackageManager.NameNotFoundException e)
            {
                e.printStackTrace();
                ToastEx.makeTextAndShowLong(e.getMessage());
            }
            return false;
        }
        return true;
    }

    @Override
    public void convertView(ViewHolder viewHolder, AppInfo item)
    {
        //当APP不可启动时，将容器背景设置为NULL，这样就不会有触发效果，但是会触发事件。
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
            viewHolder.convertView.setBackground(null);
        else
            //noinspection deprecation
            viewHolder.convertView.setBackgroundDrawable(null);

        viewHolder.getTextView(R.id.appName).setText(item.getAppName());

        if (item.isSystem())
            viewHolder.getTextView(R.id.appName).setTextColor(item.getLaunchIntent() == null ? mColorSystemAppAccentCantLaunch : mColorSystemAppAccent);
        else
            viewHolder.getTextView(R.id.appName).setTextColor(item.getLaunchIntent() == null ? mColorUserAppAccentCantLaunch : mColorUserAppAccent);

        viewHolder.getTextView(R.id.packageName).setText(item.getPackageName());

        viewHolder.getImageView(R.id.appIcon).setImageBitmap(item.getAppIcon());
        viewHolder.getImageView(R.id.appIcon).setTag(item);
        viewHolder.getImageView(R.id.appIcon).setOnClickListener(this);

        viewHolder.getImageView(R.id.status).setTag(item);
        viewHolder.getImageView(R.id.status).setOnClickListener(this);

        //假如是“快速隐藏、显示模式”时，换个图标。
        if (isQuickHideMode)
        {
            if (isOnlyShowHideApp)
                viewHolder.getImageView(R.id.status).setImageResource(R.mipmap.eye);
            else
                viewHolder.getImageView(R.id.status).setImageResource(R.mipmap.eye_closed);
        }
        else
        {
            if (item.isEnabled())
                viewHolder.getImageView(R.id.status).setImageResource(R.mipmap.widget_on);
            else
                viewHolder.getImageView(R.id.status).setImageResource(R.mipmap.widget_off);
        }

        //当此APP是系统关键APP时，不允许恢复为“非隐藏状态”、不允许“冻结”
        if (item.isAllowDisableApp == null)
            item.isAllowDisableApp = isAllowDisableApp(pm, item);
        if (item.isAllowDisableApp)
            viewHolder.getImageView(R.id.warning).setVisibility(View.INVISIBLE);
        else
            viewHolder.getImageView(R.id.warning).setVisibility(View.VISIBLE);
    }

    private void enableOrDisableApp(final AppInfo item)
    {
        new AsyncTask<Void, Void, Void>()
        {
            @Override
            protected Void doInBackground(Void... params)
            {
                if (!Shell.SU.available())
                {
                    ToastEx.makeTextAndShowLong("ROOT没有授权");
                    return null;
                }
                if (item.isEnabled())
                {
                    ToastEx.showLong("强制停止中……");
                    amForceStopApp(item.getPackageName());

                    ToastEx.showLong("强制停止 完毕\n冻结中……");
                    if (!pmDisableApp(item.getPackageName()))
                    {
                        showErrorToast("冻结失败");
                        return null;
                    }
                    item.setIsEnabled(false);
                    DBHelper.execSQLByArgs(R.string.sql_set_app_is_enabled, item.getPackageName(), item.isEnabled() ? "1" : "0");

                    ToastEx.show("强制停止 完毕\n冻结　　 成功\n清理缓存中……");
                    AppInfo.clearCacheDir(mContext, item.getPackageName());
                    ToastEx.show("强制停止 完毕\n冻结　　 成功\n清理缓存 完毕");
                    return null;
                }
                ToastEx.showLong("解冻中……");
                if (!pmEnableApp(item.getPackageName()))
                {
                    showErrorToast("解冻失败");
                    return null;
                }
                ToastEx.show("解冻成功");
                item.setIsEnabled(true);
                DBHelper.execSQLByArgs(R.string.sql_set_app_is_enabled, item.getPackageName(), item.isEnabled() ? "1" : "0");
                return null;
            }

            @Override
            protected void onPostExecute(Void aVoid)
            {
                refresh();
            }
        }.execute();
    }

    private void forceStopApp(final AppInfo appInfo)
    {
        new AsyncTask<String, String, Boolean>()
        {
            @Override
            protected Boolean doInBackground(String... params)
            {
                boolean isOk = amForceStopApp(params[0]);
                publishProgress("强制停止" + (isOk ? "成功" : "失败") + "\n清理缓存中……");

                AppInfo.clearCacheDir(mContext, appInfo.getPackageName());
                publishProgress("强制停止" + (isOk ? "成功" : "失败") + "\n清理缓存完毕");
                return isOk;
            }

            @Override
            protected void onPostExecute(Boolean result)
            {
                appInfo.setIsStopped(result);
            }

            @Override
            protected void onPreExecute()
            {
                ToastEx.show("强制停止中……");
            }

            @Override
            protected void onProgressUpdate(String... values)
            {
                ToastEx.show(values[0]);
            }
        }.execute(appInfo.getPackageName());
    }

    private void hideOrShowApp(AppInfo appInfo)
    {
        //界面移除
        getOriginaItems().remove(appInfo);
        refresh();

        //隐藏视图时，显示APP
        if (isOnlyShowHideApp)
        {
            appInfo.setIsHide(false);
            ToastEx.show(appInfo.getAppName() + " 取消隐藏完毕");
        }
        //正常视图时，隐藏APP
        else
        {
            appInfo.setIsHide(true);
            ToastEx.show(appInfo.getAppName() + " 隐藏完毕");
        }

        DBHelper.execSQLByArgs(R.string.sql_set_app_is_hide, appInfo.getPackageName(), appInfo.isHide() ? "1" : "0");
    }

    @Override
    public void onClick(View v)
    {
        AppInfo info = (AppInfo) v.getTag();
        switch (v.getId())
        {
            case R.id.appIcon:
                whenOnAppIconClick(v, info);
                break;
            case R.id.status:
                whenOnAppStatusClick(info);
                break;
        }
    }

    public boolean onContextItemSelected(MenuItem item)
    {
        int position = item.getGroupId();
        AppInfo appInfo = this.getItem(position);
        switch (item.getItemId())
        {
            case 0://详情
                openAppDetail(appInfo);
                break;
            case 1://商店
                openAppMarket(appInfo);
                break;
            case 2://隐藏
                hideOrShowApp(appInfo);
                break;
            case 3://强制停止
                forceStopApp(appInfo);
                break;
        }
        return true;
    }

    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo)
    {
        AdapterView.AdapterContextMenuInfo contextMenuInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
        AppInfo appInfo = this.getItem(contextMenuInfo.position);

        menu.setHeaderTitle(appInfo.getAppName());
        menu.add(contextMenuInfo.position, 0, 0, "详情");
        menu.add(contextMenuInfo.position, 1, 0, "商店");

        if (isOnlyShowHideApp)
            menu.add(contextMenuInfo.position, 2, 0, "显示");
        else
            menu.add(contextMenuInfo.position, 2, 0, "隐藏");

        if (!appInfo.isStopped())
            menu.add(contextMenuInfo.position, 3, 0, "强制停止");
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id)
    {
        whenOnAppNameClick(this.getItem(position));
    }

    @Override
    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id)
    {
        //长按时，会自动打开菜单时，不需要再次调用显示菜单的代码。
        //whenOnAppItemLongClick(view, this.getItem(position));

        //必须返回false，否则contextMenu无法创建，无法获得contextMenuInfo
        return false;
    }

    private void openAppDetail(AppInfo appInfo)
    {
        mContext.startActivity(newAppDetailsIntent(mContext, appInfo.getPackageName()));
    }

    private void openAppMarket(AppInfo appInfo)
    {
        try
        {
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setData(Uri.parse("market://details?id=" + appInfo.getAppName()));
            mContext.startActivity(intent);
        }
        catch (ActivityNotFoundException e)
        {
            showErrorToast("没有找到应用商店APP");
        }
    }

    private boolean pmDisableApp(String packageName)
    {
        if (Build.VERSION.SDK_INT >= 14)
            Shell.SU.run("pm disable-user " + packageName);
        else Shell.SU.run("pm disable " + packageName);
        try
        {
            ApplicationInfo info = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
            return !info.enabled;
        }
        catch (PackageManager.NameNotFoundException e)
        {
            e.printStackTrace();
            ToastEx.makeTextAndShowLong(e.getMessage());
        }
        return false;
    }

    private boolean pmEnableApp(String packageName)
    {
        Shell.SU.run("pm enable " + packageName);
        try
        {
            ApplicationInfo info = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
            return info.enabled;
        }
        catch (PackageManager.NameNotFoundException e)
        {
            e.printStackTrace();
            ToastEx.makeTextAndShowLong(e.getMessage());
        }
        return false;
    }

    public void setIsOnlyShowHideApp(boolean isOnlyShowHideApp)
    {
        this.isOnlyShowHideApp = isOnlyShowHideApp;
    }

    public void setIsQuickHideMode(boolean isQuickHideMode)
    {
        this.isQuickHideMode = isQuickHideMode;
    }

    private void showErrorToast(String msg)
    {
        ToastEx.makeTextAndShowShort(Html.fromHtml("<font color='#00ff00'>" + msg + "</font>"));
    }

    /**
     * 点击APP图标，打开菜单
     */
    private void whenOnAppIconClick(View v, AppInfo item)
    {
        this.mListView.showContextMenuForChild(v);
    }

    /**
     * 当长按APP项时
     */
    private void whenOnAppItemLongClick(View v, AppInfo item)
    {
        //默认同点击APP图标类型
        whenOnAppIconClick(v, item);
    }

    /**
     * 点击APP名字，自动启动APP（被冻结时，自动解冻后启动）
     */
    private void whenOnAppNameClick(final AppInfo item)
    {
        //当是快速隐藏、显示模式时，点击右边图标执行的就是“隐藏、显示”的功能。不再是冻结、解冻的功能。
        if (isQuickHideMode)
        {
            hideOrShowApp(item);
            return;
        }
        try
        {
            if (item.isEnabled())
            {
                ToastEx.show("启动中···");
                Intent intent = item.getLaunchIntent();
                if (intent == null)
                {
                    ToastEx.show("没有可启动的界面!");
                    return;
                }
                mContext.startActivity(intent);
                ToastEx.show("启动完毕");

                //启动完毕就关闭自身
                ((Activity) mContext).finish();
                return;
            }
            //应用被冻结时，先解冻再启动
            new AsyncTask<Void, Void, Void>()
            {
                @Override
                protected Void doInBackground(Void... params)
                {
                    if (!Shell.SU.available())
                    {
                        ToastEx.makeTextAndShowLong("ROOT没有授权");
                        return null;
                    }
                    ToastEx.showLong("解冻中……");
                    if (!pmEnableApp(item.getPackageName()))
                    {
                        showErrorToast("解冻失败");
                        return null;
                    }
                    ToastEx.show("解冻成功，启动中");

                    Intent intent = item.getLaunchIntent();
                    if (intent == null)
                    {
                        item.setLaunchIntent(intent = pm.getLaunchIntentForPackage(item.getPackageName()));

                        DBHelper.execSQLByArgs(R.string.sql_set_app_launch_intent, item.getPackageName(), item.getLaunchIntentRawData());
                    }
                    if (intent == null)
                        ToastEx.show("没有可启动的界面!");
                    else
                    {
                        mContext.startActivity(intent);
                        ToastEx.show("启动完毕");
                    }

                    item.setIsEnabled(true);

                    DBHelper.execSQLByArgs(R.string.sql_set_app_is_enabled, item.getPackageName(), item.isEnabled() ? "1" : "0");
                    return null;
                }

                @Override
                protected void onPostExecute(Void aVoid)
                {
                    //refresh();

                    //启动完毕就关闭自身
                    ((Activity) mContext).finish();
                }
            }.execute();
        }
        catch (Exception e)
        {
            LogEx.e("startActivity", e);

            ToastEx.makeTextAndShowLong(e.getMessage());
        }
    }

    /**
     * 点击状态图标，自动解冻/冻结APP
     */
    private void whenOnAppStatusClick(final AppInfo item)
    {
        //当是快速隐藏、显示模式时，点击右边图标执行的就是“隐藏、显示”的功能。不再是冻结、解冻的功能。
        if (isQuickHideMode)
        {
            hideOrShowApp(item);
            return;
        }
        //禁用状态下想启动，不用提示
        if (!item.isEnabled())
            enableOrDisableApp(item);
            //检测到不是系统核心APP
        else if (item.isAllowDisableApp)
            enableOrDisableApp(item);
            //否则需要提醒用户小心
        else
        {
            AlertDialogInner dialog = new AlertDialogInner(mContext);
            dialog.setTitle("冻结系统核心应用");
            dialog.setMessage("[可能]导致手机变砖！\n是否继续？");
            dialog.setCancelable(true);
            dialog.setButton(DialogInterface.BUTTON_POSITIVE, "是", new DialogInterface.OnClickListener()
            {
                @Override
                public void onClick(DialogInterface dialog, int which)
                {
                    AlertDialogInner alertDialog = (AlertDialogInner) dialog;
                    alertDialog.setDisableDismissFunctionOnce();
                    alertDialog.setMessage("变砖了可别怪我哦╮(╯▽╰)╭！");
                    alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "不怪你", new DialogInterface.OnClickListener()
                    {
                        @Override
                        public void onClick(DialogInterface dialog, int which)
                        {
                            enableOrDisableApp(item);
                        }
                    });
                    alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, "算了", (DialogInterface.OnClickListener) null);
                }
            });
            dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "否", (DialogInterface.OnClickListener) null);
            dialog.show();
        }
    }

    class AlertDialogInner extends AlertDialog
    {
        private boolean isDismissFunctionDisabled = false;

        protected AlertDialogInner(Context context)
        {
            super(context);
        }

        @Override
        public void dismiss()
        {
            if (isDismissFunctionDisabled)
            {
                isDismissFunctionDisabled = false;
                return;
            }
            super.dismiss();
        }

        @Override
        public void setButton(int whichButton, CharSequence text, OnClickListener listener)
        {
            super.setButton(whichButton, text, listener);

            Button tmp = getButton(whichButton);
            if (tmp != null)
                tmp.setText(text);
        }

        public void setDisableDismissFunctionOnce()
        {
            isDismissFunctionDisabled = true;
        }
    }
}
